﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using XCommunity.Frames;
using XCommunity.Views;
using System.Xml.Linq;

namespace XCommunity.Forums.Views
{
  public class ForumsViewService : ViewService
  {

    public ForumsViewService( ForumsSystem system )
      : base( system.Context )
    {
      ForumsSystem = system;
    }


    /// <summary>
    /// 所属的论坛系统
    /// </summary>
    public ForumsSystem ForumsSystem
    {
      get;
      private set;
    }


    /// <summary>
    /// 所属的社区系统
    /// </summary>
    public override ICommunitySystem CommunitySystem
    {
      get { return ForumsSystem; }
    }


    /// <summary>
    /// 视图配置节
    /// </summary>
    protected XElement Configuration
    {
      get;
      private set;
    }


    /// <summary>
    /// 初始化视图服务
    /// </summary>
    public override void Init()
    {

      Configuration = ForumsSystem.Configuration.Root.Element( ForumsSystem.XF + "views" );

      LoadConfiguration();

      base.Init();

    }


    /// <summary>
    /// 加载配置
    /// </summary>
    /// <param name="configElement"></param>
    protected virtual void LoadConfiguration()
    {
      _routeNodes = Configuration.Descendants()
         .Where( element => element.Name == ForumsSystem.XF + "forums" || element.Name == ForumsSystem.XF + "panel" )
         .ToDictionary( element => GetRoute( element ) );
    }


    /// <summary>
    /// 获取指定节点对象的路径
    /// </summary>
    /// <param name="node"></param>
    /// <returns></returns>
    protected string GetRoute( XElement node )
    {
      if ( node.Name == ForumsSystem.XF + "forums" )
        return node.Attribute( "name" ).Value;
      else
        return GetRoute( node.Parent ) + "/" + node.Attribute( "name" ).Value;
    }


    private Dictionary<string, XElement> _routeNodes = new Dictionary<string, XElement>();



    private Dictionary<string, IViewPlugin> _plugins;

    /// <summary>
    /// 根据前缀获取注册的插件。
    /// </summary>
    /// <param name="prefix">插件注册的前缀</param>
    /// <returns></returns>
    protected virtual IViewPlugin GetPlugin( string prefix )
    {

      var plugin = ForumsSystem.Plugins.Single( item => item.Prefix == prefix ) as IViewPlugin;
      if ( plugin == null )
        throw new ArgumentException( string.Format( "找不到前缀为 \"{0}\" 的视图插件" ), "prefix" ); //UNDONE 异常详细信息

      return plugin;
    }


    /// <summary>
    /// 
    /// </summary>
    /// <param name="viewObject"></param>
    /// <param name="name"></param>
    /// <returns></returns>
    public override object GetValue( ViewObject viewObject, string name )
    {

      int index = name.IndexOf( ':' );

      if ( index != -1 )
      {

        string propertyPrefix = name.Substring( 0, index );
        string properyName = name.Substring( index + 1 );
        return GetPlugin( propertyPrefix ).GetValue( viewObject, properyName );

      }

      return base.GetValue( viewObject, name );
    }



    /// <summary>
    /// 获取论坛视图
    /// </summary>
    /// <returns></returns>
    public virtual ForumsView GetForumsView()
    {

      var forumsElement = Configuration.Elements( "forums" ).Where( element => element.Attribute( "name" ).Value == Configuration.Attribute( "default-forums" ).Value ).Single();

      ForumsView view = new ForumsView( this, forumsElement );

      return view;

    }

    /// <summary>
    /// 通过路径获取对应的视图对象
    /// </summary>
    /// <param name="route">路径</param>
    /// <returns></returns>
    public virtual ViewObject GetView( string route )
    {

      string lastNode = route.Split( '/' ).Last();

      if ( lastNode.StartsWith( "#" ) )
      {
        int topicId = int.Parse( lastNode.TrimStart( '#' ) );

        return GetTopicFrameView( topicId );
      }
      else
      {

        XElement element;

        if ( !_routeNodes.TryGetValue( route, out element ) )
        {
          throw new Exception( "找不到路径" );//UNDONE 详细的异常信息
        }



        if ( element.Name == ForumsSystem.XF + "panel" )
        {

          var boardFrame = GetBoardFrame( element );

          if ( boardFrame == null )
            return new PanelFrameView( this, element );
          else
            return new BoardFrameView( this, element, boardFrame );

        }
        else if ( element.Name == ForumsSystem.XF + "forums" )
          return new ForumsView( this, element );
      }

      throw new NotSupportedException();
    }








    /// <summary>
    /// 获取话题框架
    /// </summary>
    /// <param name="topicId"></param>
    /// <returns></returns>
    protected GeneralTopicFrame GetTopicFrame( int topicId )
    {
      return (GeneralTopicFrame) ForumsSystem.Context.FrameService.GetTopicFrame( topicId );
    }


    /// <summary>
    /// 获取话题列表项视图
    /// </summary>
    /// <param name="topic"></param>
    /// <returns></returns>
    public TopicItemView GetTopicItemView( ITopicFrame topic )
    {
      return new TopicItemView( this, topic );
    }



    /// <summary>
    /// 获取话题框架视图
    /// </summary>
    /// <param name="_topicId"></param>
    /// <returns></returns>
    public ViewObject GetTopicFrameView( int topicId )
    {
      return GetTopicFrameView( GetTopicFrame( topicId ) );
    }


    /// <summary>
    /// 获取话题框架视图
    /// </summary>
    /// <param name="topic"></param>
    /// <returns></returns>
    public TopicFrameView GetTopicFrameView( GeneralTopicFrame topic )
    {
      OnTopicBrowsed( this, new BrowseEventArgs() { FrameObject = topic } );

      return new TopicFrameView( this, topic );
    }



    /// <summary>
    /// 获取帖子框架视图
    /// </summary>
    /// <param name="post"></param>
    /// <returns></returns>
    public PostFrameView GetPostFrameView( GeneralPostFrame post )
    {
      return new PostFrameView( this, post );
    }

    /// <summary>
    /// 获取导航器视图
    /// </summary>
    /// <param name="route"></param>
    /// <returns></returns>
    public virtual NavigatorView GetNavigatorView( string route )
    {
      return new NavigatorView( this, route );
    }



    /// <summary>
    /// 引发BoardBrowsed事件
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    protected virtual void OnBoardBrowsed( object sender, BrowseEventArgs e )
    {
      if ( BoardBrowsed != null )
        BoardBrowsed( sender, e );
    }

    protected virtual void OnTopicBrowsed( object sender, BrowseEventArgs e )
    {
      if ( TopicBrowsed != null )
        TopicBrowsed( sender, e );
    }



    public event EventHandler<BrowseEventArgs> BoardBrowsed;

    public event EventHandler<BrowseEventArgs> TopicBrowsed;



    protected ForumsBoardFrame GetBoardFrame( XElement element )
    {
      var boardAttribute = element.Attribute( "board" );

      if ( boardAttribute == null )
        return null;

      ForumsBoardFrame boardFrame = ForumsSystem.GetBoard( boardAttribute.Value );
      if ( boardFrame == null )
      {
        throw new ConfigurationErrorException( string.Format( "无效的frame设置，找不到版面“{0}”", boardAttribute.Value ), element.Attribute( "board" ) );
      }

      return boardFrame;
    }


    public string GetTitle( string route )
    {

      string lastNode = route.Split( '/' ).Last();
      if ( lastNode.StartsWith( "#" ) )
      {
        return GetTopicFrame( int.Parse( lastNode.TrimStart( '#' ) ) ).Meta.Title;
      }


      XElement element;

      if ( !_routeNodes.TryGetValue( route, out element ) )
        throw new ArgumentException( "找不到路径", "route" );


      return element.Element( ForumsSystem.XF + "title" ).Value;

    }

  }



  public class BrowseEventArgs : EventArgs
  {
    public object FrameObject
    {
      get;
      internal set;
    }
  }

}
